using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace cs2335.CCT
{
    public class DomainUpDown : IComponent, IDomainUpDown
    {
        protected Rectangle upDownRectangle = new Rectangle(0, 0, 100, 20);
        protected Rectangle upButton;
        protected Rectangle downButton;
        protected StringFormat labelFormat = new StringFormat(StringFormatFlags.NoClip);
        protected SolidBrush upDownBrush = new SolidBrush(Color.White);
        protected SolidBrush buttonBrush = new SolidBrush(Color.Blue);
        protected SolidBrush tBrush = new SolidBrush(Color.Gold);
        protected Font font = new Font("SansSerif", 10);
        protected CCTForm owner;
        protected string text;
        protected bool hasFocus = false;
        protected bool hidden = false;
        protected string name;
        protected System.Collections.ArrayList list;
        protected int index = 0;
        protected bool isSorted;

        #region Properties
        public Point Location
        {
            get { return upDownRectangle.Location; }
            set { upDownRectangle.Location = value; Invalidate(); }
        }

        public Rectangle Bounds
        {
            get { return upDownRectangle; }
            set { upDownRectangle = value; Invalidate(); }
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public System.Drawing.Font Font
        {
            get { return font; }
            set { font = value; Invalidate(); }
        }

        public string Text
        {
            get { return text; }
            set { text = value; Invalidate(); }
        }

        public CCTForm Owner
        {
            get { return owner; }
            set { owner = value; }
        }

        public Color BackColor
        {
            get { return upDownBrush.Color; }
            set { upDownBrush.Color = value; Invalidate(); }
        }
        #endregion

        #region Events
        public event EventHandler Click;
        public event EventHandler GotFocus;
        public event EventHandler KeyPress;
        public event EventHandler LostFocus;
        public event EventHandler Paint;
        public event EventHandler KeyDown;
        #endregion

        public DomainUpDown()
        {
            list = new System.Collections.ArrayList();
        }


        /// <summary>
        /// Notifies its CCTForm that it needs a redraw
        /// </summary>
        public void Invalidate()
        {
            if (owner != null)
            {
                owner.Invalidate();
            }
        }


        /// <summary>
        /// Conceals the component from the user.
        /// </summary>
        public void Hide()
        {
            hidden = true;
            Invalidate();
        }


        /// <summary>
        /// Displays the component to the user.
        /// </summary>
        public void Show()
        {
            hidden = false;
            Invalidate();
        }

        /// <summary>
        /// Raises the Paint event
        /// </summary>
        /// <param name="e">A PaintEventArgs that contains the event data</param>
        public void OnPaint(PaintEventArgs e)
        {
            if (!hidden)
            {
                int x = upDownRectangle.X;
                int y = upDownRectangle.Y;
                int w = upDownRectangle.Width;

                upButton = new Rectangle((x + w) - 10, y, 10, 10);
                downButton = new Rectangle((x + w) - 10, y + 10, 10, 10);

                Graphics g = e.Graphics;

                g.FillRectangle(upDownBrush, upDownRectangle);
                g.FillRectangle(buttonBrush, upButton);
                g.FillRectangle(buttonBrush, downButton);

                // Triangles (point arrays) for up and down buttons
                Point[] uptriangle = {new Point(upButton.X+1,upButton.Y+8),new Point(upButton.X+5,upButton.Y+2),
                        new Point(upButton.X+9,upButton.Y+8)};
                Point[] downtriangle = {new Point(downButton.X+1,downButton.Y+2),new Point(downButton.X+5,downButton.Y+8),
                        new Point(downButton.X+9,downButton.Y+2)};

                //draw triangles
                g.FillPolygon(tBrush, uptriangle);
                g.DrawPolygon(Pens.Black, uptriangle);
                g.FillPolygon(tBrush, downtriangle);
                g.DrawPolygon(Pens.Black, downtriangle);
                
                //Draw Borders
                g.DrawRectangle(Pens.Black, upButton);
                g.DrawRectangle(Pens.Black, downButton);
                g.DrawRectangle(Pens.Gray, upDownRectangle);
                if (hasFocus)
                {

                    g.DrawRectangle(Pens.LightBlue, upDownRectangle.X-1, upDownRectangle.Y-1, upDownRectangle.Width+2, upDownRectangle.Height+2);
                }

                //Get string
                text = (string)list[index];
                g.DrawString(text, font, Brushes.Black, (RectangleF)upDownRectangle, labelFormat);

                if (Paint != null)
                {
                    Paint(this, e);
                }
            }
        }


        /// <summary>
        /// Raises the GotFocus event
        /// </summary>
        /// <param name="e">An EventArgs that contains the event data</param>
        public void OnGotFocus(EventArgs e)
        {
            hasFocus = true;
            if (GotFocus != null)
            {
                GotFocus(this, e);
            }
            owner.Invalidate();
        }


        /// <summary>
        /// Raises the LostFocus event
        /// </summary>
        /// <param name="e">An EventArgs that contains the event data</param>
        public void OnLostFocus(EventArgs e)
        {
            hasFocus = false;
            if (LostFocus != null)
            {
                LostFocus(this, e);
            }
            owner.Invalidate();
        }


        /// <summary>
        /// Called when the mouse is clicked on the component
        /// </summary>
        /// <param name="e">A MouseEventArgs that contains the event data</param>
        public void OnMouseClick(System.Windows.Forms.MouseEventArgs e)
        {
            /* what's gonna go on here is that if one of the buttons are clicked
             * (within the range upDownRectange.Width-buttonLength and height)
             * then the text in the box will scroll from one element in the set
             * to the next.
             */
            if (upButton.Contains(e.X, e.Y))
            {
                if (index > 0)
                {
                    index--;
                    Invalidate();
                }
            }
            if (downButton.Contains(e.X, e.Y))
            {
                if (index < list.Count - 1)
                {
                    index++;                    
                    Invalidate();
                }
            }
            if (Click != null)
            {
                Click(this, e);
            }
        }

        /// <summary>
        /// Called when a key is pressed when the component has focus
        /// </summary>
        /// <param name="e">A KeyPressEventArgs that contains the event data</param>
        public void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
        {
            if (KeyPress != null)
            {
                KeyPress(this, e);
            }

        }

        public void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyData == Keys.Up)
            {
                if (index > 0)
                {
                    index--;
                    Invalidate();
                }
            }
            if (e.KeyData == Keys.Down)
            {
                if (index < list.Count - 1)
                {
                    index++;
                    Invalidate();
                }
            }
            
            if (KeyDown != null)
            {
                KeyDown(this, e);
            }
        }


        #region IDomainUpDown Members

        public System.Collections.ArrayList Items
        {
            get { return list; }

            set { list = value; list.Sort(); }
        }

        public bool Sorted
        {
            get
            {
                return isSorted;
            }
            set
            {
                isSorted = value;
            }
        }

        public object SelectedItem
        {
            get
            {
                return list[index];
            }
            set
            {
                list[index] = value;
                Invalidate();
            }
        }

        public int SelectedIndex
        {
            get
            {
                return index;
            }
            set
            {
                index = value;
                Invalidate();
            }
        }

        #endregion

    }
    

}
